"""
校园新生指引程序 - 地图可视化模块
使用matplotlib绘制校园点线图
"""

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
from typing import List, Dict
from models import CampusMap, Point, Road

# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False


class MapVisualizer:
    """地图可视化器"""
    
    def __init__(self, campus_map: CampusMap):
        self.campus_map = campus_map
        self.fig = None
        self.ax = None
        self.canvas = None
    
    def create_figure(self, width=10, height=8):
        """创建matplotlib图形"""
        self.fig, self.ax = plt.subplots(figsize=(width, height))
        self.ax.set_title('校园导航地图', fontsize=16, fontweight='bold')
        self.ax.set_xlabel('X坐标')
        self.ax.set_ylabel('Y坐标')
        self.ax.grid(True, alpha=0.3)
        
        # 设置坐标轴范围（根据点位坐标自动调整）
        if self.campus_map.points:
            x_coords = [point.x for point in self.campus_map.points.values()]
            y_coords = [point.y for point in self.campus_map.points.values()]
            margin = 10  # 边距
            self.ax.set_xlim(min(x_coords) - margin, max(x_coords) + margin)
            self.ax.set_ylim(min(y_coords) - margin, max(y_coords) + margin)
        else:
            self.ax.set_xlim(0, 100)
            self.ax.set_ylim(0, 100)
    
    def draw_map(self, highlight_path: List[str] = None):
        """绘制地图"""
        if not self.ax:
            self.create_figure()
        
        self.ax.clear()
        
        # 设置背景色和样式
        self.ax.set_facecolor('#f8f9fa')
        self.ax.set_title('校园导航地图', fontsize=18, fontweight='bold', color='#2c3e50', pad=20)
        self.ax.set_xlabel('X坐标', fontsize=12, color='#7f8c8d')
        self.ax.set_ylabel('Y坐标', fontsize=12, color='#7f8c8d')
        self.ax.grid(True, alpha=0.2, linestyle='--', linewidth=0.5)
        
        # 绘制道路
        for road in self.campus_map.roads.values():
            point1 = self.campus_map.points[road.point1_id]
            point2 = self.campus_map.points[road.point2_id]
            
            # 检查道路是否在突出显示的路径中
            is_highlighted = False
            if highlight_path:
                for i in range(len(highlight_path) - 1):
                    if (highlight_path[i] == road.point1_id and highlight_path[i + 1] == road.point2_id) or \
                       (highlight_path[i] == road.point2_id and highlight_path[i + 1] == road.point1_id):
                        is_highlighted = True
                        break
            
            if is_highlighted:
                # 高亮路径 - 使用醒目的颜色
                line_style = '-'
                line_width = 4
                line_color = '#e74c3c'  # 红色
                line_alpha = 0.9
            else:
                # 普通道路 - 使用柔和的颜色
                line_style = '-'
                line_width = 2
                line_color = '#95a5a6'  # 灰色
                line_alpha = 0.6
            
            self.ax.plot([point1.x, point2.x], [point1.y, point2.y], 
                        linestyle=line_style, linewidth=line_width, 
                        color=line_color, alpha=line_alpha, zorder=1)
            
            # 显示道路距离
            mid_x = (point1.x + point2.x) / 2
            mid_y = (point1.y + point2.y) / 2
            self.ax.text(mid_x, mid_y, f'{road.distance}m', 
                        fontsize=9, color='#2980b9', ha='center', va='center',
                        bbox=dict(boxstyle="round,pad=0.2", facecolor="#ecf0f1", alpha=0.9, edgecolor='#bdc3c7'),
                        zorder=2)
        
        # 绘制点位
        for point in self.campus_map.points.values():
            # 检查点位是否在突出显示的路径中
            is_highlighted = highlight_path and point.id in highlight_path
            
            if is_highlighted:
                # 高亮点位 - 使用醒目的颜色
                point_color = '#e74c3c'  # 红色
                point_size = 120
                edge_color = '#c0392b'
                text_color = '#c0392b'
            else:
                # 普通点位 - 使用主题色
                point_color = '#3498db'  # 蓝色
                point_size = 80
                edge_color = '#2980b9'
                text_color = '#2c3e50'
            
            # 绘制点位（圆形）
            self.ax.scatter(point.x, point.y, s=point_size, c=point_color, 
                           alpha=0.9, edgecolors=edge_color, linewidths=2, zorder=3)
            
            # 在点位中心添加白色圆点
            self.ax.scatter(point.x, point.y, s=20, c='white', alpha=0.8, zorder=4)
            
            # 显示点位名称和功能
            functions_text = ' | '.join(point.functions[:2])  # 只显示前两个功能
            if len(point.functions) > 2:
                functions_text += ' ...'
            
            text = f'{point.name}\n{functions_text}'
            
            # 调整文本位置避免重叠
            offset_x = 3
            offset_y = 3
            
            self.ax.annotate(text, (point.x, point.y),
                            xytext=(point.x + offset_x, point.y + offset_y),
                            fontsize=10, color=text_color, weight='bold',
                            bbox=dict(boxstyle="round,pad=0.4", facecolor="white", alpha=0.95, 
                                    edgecolor='#bdc3c7', linewidth=1),
                            arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=0.1", 
                                          color='#7f8c8d', alpha=0.7),
                            zorder=5)
        
        # 设置坐标轴范围
        if self.campus_map.points:
            x_coords = [point.x for point in self.campus_map.points.values()]
            y_coords = [point.y for point in self.campus_map.points.values()]
            margin = 15
            self.ax.set_xlim(min(x_coords) - margin, max(x_coords) + margin)
            self.ax.set_ylim(min(y_coords) - margin, max(y_coords) + margin)
        
        self.ax.set_aspect('equal')
        
        # 添加图例说明
        legend_elements = [
            plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='#3498db', markersize=10, label='普通点位'),
            plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='#e74c3c', markersize=10, label='路径点位'),
            plt.Line2D([0], [0], color='#95a5a6', lw=2, label='普通道路'),
            plt.Line2D([0], [0], color='#e74c3c', lw=3, label='规划路径')
        ]
        self.ax.legend(handles=legend_elements, loc='upper right', framealpha=0.9)
        
        if self.canvas:
            self.canvas.draw()
    
    def create_tk_canvas(self, parent):
        """创建Tkinter画布用于嵌入matplotlib图形"""
        if not self.fig:
            self.create_figure()
        
        self.canvas = FigureCanvasTkAgg(self.fig, master=parent)
        self.canvas.draw()
        return self.canvas.get_tk_widget()
    
    def update_map(self, highlight_path: List[str] = None):
        """更新地图显示"""
        self.draw_map(highlight_path)
        if self.canvas:
            self.canvas.draw()
    
    def save_map_image(self, filename: str):
        """保存地图为图片"""
        if not self.fig:
            self.create_figure()
        
        self.draw_map()
        self.fig.savefig(filename, dpi=300, bbox_inches='tight')
        print(f"地图已保存为: {filename}")


class MapEditor:
    """地图编辑器，用于手动调整点位位置和绘制标记"""
    
    def __init__(self, campus_map: CampusMap, visualizer: MapVisualizer):
        self.campus_map = campus_map
        self.visualizer = visualizer
        self.selected_point = None
        self.dragging = False
        self.canvas = None
        self.markers = []  # 存储标记方块
        self.drawing_mode = False  # 绘制模式标志
        self.current_marker = None  # 当前正在绘制的标记
    
    def on_click(self, event):
        """鼠标点击事件处理"""
        if event.inaxes != self.visualizer.ax:
            return
        
        # 查找点击的点位
        clicked_point = self._find_point_at_position(event.xdata, event.ydata)
        
        if clicked_point:
            self.selected_point = clicked_point
            self.dragging = True
            print(f"选中点位: {clicked_point.name}")
            return True  # 表示已选中点位
        return False
    
    def on_release(self, event):
        """鼠标释放事件处理"""
        if self.dragging and self.selected_point:
            print(f"点位 {self.selected_point.name} 已移动到新位置: ({self.selected_point.x:.1f}, {self.selected_point.y:.1f})")
        self.dragging = False
        self.selected_point = None
    
    def on_motion(self, event):
        """鼠标移动事件处理"""
        if self.dragging and self.selected_point and event.inaxes == self.visualizer.ax:
            # 更新点位位置
            self.selected_point.x = event.xdata
            self.selected_point.y = event.ydata
            
            # 实时重绘地图
            self.visualizer.update_map()
    
    def _find_point_at_position(self, x: float, y: float, tolerance: float = 8.0) -> Point:
        """在指定位置查找点位"""
        for point in self.campus_map.points.values():
            distance = ((point.x - x) ** 2 + (point.y - y) ** 2) ** 0.5
            if distance <= tolerance:
                return point
        return None
    
    def connect_events(self, canvas):
        """连接鼠标事件"""
        self.canvas = canvas
        canvas.mpl_connect('button_press_event', self.on_click)
        canvas.mpl_connect('button_release_event', self.on_release)
        canvas.mpl_connect('motion_notify_event', self.on_motion)
    
    def add_marker(self, x: float, y: float, width: float = 10, height: float = 10, 
                  color: str = '#FFD700', alpha: float = 0.3, label: str = ""):
        """添加标记方块"""
        marker = {
            'x': x,
            'y': y,
            'width': width,
            'height': height,
            'color': color,
            'alpha': alpha,
            'label': label
        }
        self.markers.append(marker)
        self.draw_markers()
    
    def remove_marker(self, index: int):
        """删除指定索引的标记"""
        if 0 <= index < len(self.markers):
            self.markers.pop(index)
            self.draw_markers()
    
    def clear_markers(self):
        """清除所有标记"""
        self.markers.clear()
        self.draw_markers()
    
    def draw_markers(self):
        """绘制所有标记方块"""
        # 确保图形已初始化
        if not self.visualizer.ax:
            self.visualizer.create_figure()
        
        # 清除之前的标记
        if hasattr(self.visualizer.ax, 'patches'):
            for patch in self.visualizer.ax.patches:
                if hasattr(patch, 'is_marker') and patch.is_marker:
                    patch.remove()
        
        # 绘制新的标记
        for i, marker in enumerate(self.markers):
            rect = patches.Rectangle(
                (marker['x'] - marker['width']/2, marker['y'] - marker['height']/2),
                marker['width'], marker['height'],
                linewidth=2, edgecolor=marker['color'], 
                facecolor=marker['color'], alpha=marker['alpha'],
                zorder=6
            )
            rect.is_marker = True  # 标记为自定义标记
            self.visualizer.ax.add_patch(rect)
            
            # 添加标签
            if marker['label']:
                self.visualizer.ax.text(
                    marker['x'], marker['y'] + marker['height']/2 + 2,
                    marker['label'], fontsize=9, color=marker['color'],
                    ha='center', va='bottom', weight='bold',
                    bbox=dict(boxstyle="round,pad=0.2", facecolor="white", alpha=0.8)
                )
        
        if self.visualizer.canvas:
            self.visualizer.canvas.draw()
    
    def disconnect_events(self):
        """断开鼠标事件连接"""
        if self.canvas:
            # 在Tkinter中，断开事件连接比较复杂
            # 我们通过设置标志位来禁用拖拽功能
            self.dragging = False
            self.selected_point = None
